home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / shells / rc-1.000 / rc-1 / rc-1.5-linux / b_test.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-28  |  6.5 KB  |  171 lines

  1. /* fully GNU plug-in test, but much cleaner, a little faster, and a lot smaller.
  2.    (100 lines instead of 1000; binary is 4K instead of 18K on an i486-Linux)
  3.    *loosely* based upon 'v7test.c' at uunet, but cleaned up and much enhanced.
  4.                                                             Charles Blake, 1994
  5.  
  6. test has the following grammar:
  7. expr   ::= bexpr | bexpr -o expr ;
  8. bexpr  ::= primary | primary -a bexpr ;
  9. primary::= unary-operator operand
  10.          | operand binary-operator operand
  11.          | operand
  12.          | "(" expr ")"
  13.          | "!" expr
  14. unary-operator::= "-"+ r|w|x|f|d|s|t|e|S|p|c|b|L|h|k|u|g|O|G|z|n
  15. binary-operator::= -nt|-ot|-ef|=|!=|-eq|-ne|-ge|-gt|-le|-lt
  16. operand ::= <any legal UNIX file name>
  17. */
  18.  
  19. #include <unistd.h>
  20. #include <stdlib.h>
  21. #include <sys/types.h>
  22. #include <sys/stat.h>
  23.  
  24. enum opnum { EOI,FILRD,FILWR,FILEX,FILND,FILID,FILGZ,FILTT,FILPR,FILSO,FILFF,
  25.         FILCS,FILBS,FILSL,FILHL,FILSB,FILUI,FILGI,FILOU,FILOG,FNEWR,FOLDR,FSAME,
  26.         STZER,STNZE,STEQL,STNEQ,INTEQ,INTNE,INTGE,INTGT,INTLE,INTLT,
  27.         UNEGN,BAND,BOR,LPAREN,RPAREN,OPERAND};
  28.  
  29. enum optype { UNOP, BINOP, BUNOP, BBINOP, PAREN }; /* maybe UNOP=1 ? */
  30.  
  31. struct T_sop {
  32.     char *text; enum opnum num; enum optype type;
  33. }T_ops[]={{"-r", FILRD, UNOP},  {"-w", FILWR, UNOP},  {"-x", FILEX, UNOP},
  34.           {"-f", FILND, UNOP},  {"-d", FILID, UNOP},  {"-s", FILGZ, UNOP},   
  35.           {"-t", FILTT, UNOP},  {"-e", FILPR, UNOP},  {"-S", FILSO, UNOP},
  36.           {"-p", FILFF, UNOP},  {"-c", FILCS, UNOP},  {"-b", FILBS, UNOP},
  37.           {"-L", FILSL, UNOP},  {"-h", FILHL, UNOP},  {"-k", FILSB, UNOP},
  38.           {"-u", FILUI, UNOP},  {"-g", FILGI, UNOP},  {"-O", FILOU, UNOP},
  39.           {"-G", FILOG, UNOP},  {"-nt",FNEWR, BINOP}, {"-ot",FOLDR, BINOP},
  40.           {"-ef",FSAME, BINOP}, {"-z", STZER, UNOP},  {"-n", STNZE, UNOP},
  41.           {"=",  STEQL, BINOP}, {"!=", STNEQ, BINOP}, {"-eq",INTEQ, BINOP},
  42.           {"-ne",INTNE, BINOP}, {"-ge",INTGE, BINOP}, {"-gt",INTGT, BINOP},
  43.           {"-le",INTLE, BINOP}, {"-lt",INTLT, BINOP}, {"!",  UNEGN, BUNOP},
  44.           {"-a", BAND,  BBINOP},{"-o", BOR,   BBINOP},{"(",  LPAREN,PAREN},
  45.           {")",  RPAREN,PAREN}, {  0,    0,     0}};
  46.  
  47. char** T_ip;
  48. struct T_sop *T_op;
  49. int T_error=0;
  50.  
  51. #ifdef ADDON
  52.  
  53. #include "addon.h"
  54. typedef enum bool { FALSE, TRUE } bool;
  55. extern void set(bool);
  56. void b_test(char* argv[]) {
  57.     int i=0;                   /* truncate off possible trailing ']' s */
  58.     while (argv[i]!=0) i++;
  59.     if (argv[i-1][0]==']') argv[i-1]=0;
  60.     T_ip = &argv[1];
  61.     if (T_error==1) { set(FALSE); return; }
  62.     if ((!(T_expr(T_lex(*T_ip)) && *++T_ip == 0))==0)
  63.         set(TRUE);
  64.     else
  65.         set(FALSE);
  66. }
  67.  
  68. #else
  69. int main(int argc, char* argv[]) {
  70.     int i=0;
  71.     while (argv[i]!=0) i++;  /* truncate off possible trailing ']' s */
  72.     if (argv[i-1][0]==']') argv[i-1]=0;
  73.     T_ip = &argv[1];
  74.     return(T_error==1 || !(T_expr(T_lex(*T_ip))&& *++T_ip == 0));
  75. }
  76. #endif /* ADDON */
  77.  
  78. int T_expr(int n) {
  79.     int res;
  80.     if (n==EOI) { T_error=1; return 1; }
  81.     res=T_bexpr(n);
  82.     if (T_lex(*++T_ip)==BOR) return T_expr(T_lex(*++T_ip)) || res;
  83.     T_ip--;
  84.     return res;
  85. }
  86.  
  87. int T_bexpr(int n) {
  88.     int res;
  89.     if (n == EOI) { T_error=1; return 1;}
  90.     res = T_primary(n);
  91.     if (T_lex(*++T_ip) == BAND) return T_bexpr(T_lex(*++T_ip)) && res;
  92.     T_ip--;
  93.     return res;
  94. }
  95.  
  96. int T_primary(int n) {
  97.     struct stat s, s2;
  98.     char *opnd1, *opnd2;
  99.     int res;
  100.  
  101.     if (n==EOI) { T_error=1; return 1;}
  102.     if (n==UNEGN) return !T_expr(T_lex(*++T_ip));
  103.     if (n==LPAREN) {
  104.         res=T_expr(T_lex(*++T_ip));
  105.         if (T_lex(*++T_ip) != RPAREN) { T_error=1; return 1;}
  106.         return res;
  107.     }
  108.     if (n==OPERAND) {
  109.         opnd1= *T_ip;
  110.         (void) T_lex(*++T_ip);
  111.         if (T_op && T_op->type==BINOP) {
  112.             struct T_sop *op = T_op;
  113.             if ((opnd2 = *++T_ip) == (char *)0) { T_error=1; return 1;}
  114.             switch (op->num) {
  115.             case STEQL: return strcmp(opnd1, opnd2) == 0;
  116.             case STNEQ: return strcmp(opnd1, opnd2) != 0;
  117.             case INTEQ: return atoi(opnd1) == atoi(opnd2);
  118.             case INTNE: return atoi(opnd1) != atoi(opnd2);
  119.             case INTGE: return atoi(opnd1) >= atoi(opnd2);
  120.             case INTGT: return atoi(opnd1) > atoi(opnd2);
  121.             case INTLE: return atoi(opnd1) <= atoi(opnd2);
  122.             case INTLT: return atoi(opnd1) < atoi(opnd2);
  123.             case FNEWR: return stat(opnd1,&s)==0 && stat(opnd2,&s2)==0 && s.st_mtime > s2.st_mtime;
  124.             case FOLDR: return stat(opnd1,&s)==0 && stat(opnd2,&s2)==0 && s.st_mtime < s2.st_mtime;
  125.             case FSAME: return stat(opnd1,&s)==0 && stat(opnd2,&s2)==0 && s.st_ino==s2.st_ino && s.st_dev==s2.st_dev;
  126.             }
  127.         }
  128.         T_ip--;
  129.         return strlen(opnd1) > 0;
  130.     }
  131.     /* unary expression */
  132.     if (T_op->type != UNOP || *++T_ip == 0) { T_error=1; return 1;}
  133.     if (n == STZER) return strlen(*T_ip) == 0;
  134.     if (n == STNZE) return strlen(*T_ip) != 0;
  135.     switch (n) {
  136.         case FILRD: return access(*T_ip,R_OK)==0;
  137.         case FILWR: return access(*T_ip,W_OK)==0;
  138.         case FILEX: return access(*T_ip,X_OK)==0;
  139.         case FILND: return stat(*T_ip,&s)==0 && ((s.st_mode & S_IFMT)!=S_IFDIR);
  140.         case FILID: return stat(*T_ip,&s)==0 && ((s.st_mode & S_IFMT)==S_IFDIR);
  141.         case FILGZ: return stat(*T_ip,&s)==0 && (s.st_size > 0L);
  142.         case FILTT: T_error=1; return 1; /* unimplimented */
  143.         case FILPR: return stat(*T_ip,&s)==0;
  144.         case FILSO: return stat(*T_ip,&s)==0 && ((s.st_mode & S_IFMT)==S_IFSOCK);
  145.         case FILFF: return stat(*T_ip,&s)==0 && ((s.st_mode & S_IFMT)==S_IFIFO);
  146.         case FILCS: return stat(*T_ip,&s)==0 && ((s.st_mode & S_IFMT)==S_IFCHR);
  147.         case FILBS: return stat(*T_ip,&s)==0 && ((s.st_mode & S_IFMT)==S_IFBLK);
  148.         case FILSL: return lstat(*T_ip,&s)==0&& ((s.st_mode & S_IFMT)==S_IFLNK);
  149.         case FILHL: return stat(*T_ip,&s)==0 && (s.st_nlink > 1);
  150.         case FILSB: return stat(*T_ip,&s)==0 && (s.st_mode & S_ISVTX)==S_ISVTX;
  151.         case FILUI: return stat(*T_ip,&s)==0 && (s.st_mode & S_ISUID)==S_ISUID;
  152.         case FILGI: return stat(*T_ip,&s)==0 && (s.st_mode & S_ISGID)==S_ISGID;
  153.         case FILOU: return stat(*T_ip,&s)==0 && (s.st_uid==geteuid());
  154.         case FILOG: return stat(*T_ip,&s)==0 && (s.st_uid==geteuid());
  155.     }
  156. }
  157.  
  158. int T_lex(char* s) {
  159.     struct T_sop *op = T_ops;
  160.     if (s == 0) return EOI;
  161.     while (op->text) {
  162.         if (strcmp(s, op->text) == 0) {
  163.             T_op = op;
  164.             return op->num;
  165.         }
  166.         op++;
  167.     }
  168.     T_op = (struct T_sop *)0;
  169.     return OPERAND;
  170. }
  171.